Skip to content

feat: SSM/STS, Lambda provided runtimes, and Redshift COPY on PostgreSQL for local data loads - #17

Merged
simota merged 15 commits into
mainfrom
feat/csa-local-aws
Nov 3, 2026
Merged

simota merged 15 commits into
mainfrom
feat/csa-local-aws

Conversation

@simota

@simota simota commented Nov 3, 2026 •

Copy link
Copy Markdown
Owner

変更の目的

pushone-csa の data_load を devcloud だけでローカル実行するのに足りなかった機能を追加しました。SSM と STS を新しいサービスとして実装し、Lambda で provided* ランタイム(Go の runner)を実行できるようにしました。また Redshift の PostgreSQL バックエンドで、COPY ... FROM 's3://...' を使えるようにしました。

主な変更

  • SSM Parameter Store(新規、ポート 18031): PutParameter / GetParameter(SecureString と WithDecryption)/ DeleteParameter / DescribeParameters を、AWS JSON 1.1 プロトコルで提供します。state.json に保存します。KMS は無いため、SecureString の値は平文で保存します。WithDecryption を付けない取得には、平文ではなく不透明な値を返します。dashboard には一覧(値は出さない)を追加しました。
  • STS(新規、ポート 18032): AssumeRole と GetCallerIdentity を AWS Query プロトコルで提供します。インラインの Policy は JSON として正しいかだけを確かめ、権限の評価はしません。状態は持ちません。
  • 組み込み: 設定、supervisor、dashboard のページと API、e2e スクリプト、golden ファイルに追加しました。新しいサービスは既定で有効になるため、既存の e2e / verify スクリプト 25 本では ssm と sts を明示的に無効にしています。
  • Lambda の provided* ランタイム: bootstrap をローカルのプロセスとして起動し、実行環境ごとに Lambda Runtime API(AWS_LAMBDA_RUNTIME_API)を立てます。対応しているのは invocation/next・response・error・init/error、chunked 形式の本文と trailer です。実行環境は再利用され、ログは呼び出しごとに分割されます。bootstrap が見つからない、または別の OS 向けのバイナリの場合は、Runtime.InvalidEntrypoint を返します。Extensions API は登録だけ受け付け、イベントは送りません。
  • Redshift(PostgreSQL バックエンド):
    • pgwire のクライアント接続ごとに専用の PostgreSQL セッションを持たせました。これまでは全クライアントが 1 本の接続を共有していたため、一時テーブルやトランザクションがクライアント間で混ざり、切断後も残っていました。
    • COPY ... FROM 's3://bucket/prefix' を devcloud 側で処理し、そのクライアントのセッション上で取り込みます。対応形式は text/DELIMITER、CSV、JSON 'auto'、GZIP、IGNOREHEADER、NULL AS、EMPTYASNULL、BLANKSASNULL です。空のフィールドを NULL にするかどうかは Redshift の規則に合わせました。対応していないオプションは無視せずエラーにします。
    • README の「COPY / UNLOAD: Yes」は実態と合っていなかったので直しました(UNLOAD は今もメモリバックエンドのみ)。
  • CI の修正: vite を 6.4.5 に上げました。6.4.4 に新しく GHSA-8g5g-mxqh-grgj(moderate)が出て、npm audit が落ちていたためです。ビルドされる bundle は変わりません。ブラウザでのスモークテストが想定するサービス数も、12 から 14 に直しました。

検証

検証 結果
cargo test --workspace 1,624 passed / 0 failed
scripts/ssm-e2e.sh / scripts/sts-e2e.sh / scripts/lambda-e2e.sh / scripts/redshift-e2e.sh すべて成功(macOS の bash 3.2)
dashboard の npm run typecheck / npm run build / npm test / npm run test:browser(Chromium) 成功
npm audit / cargo audit 脆弱性 0 件 / 失敗なし(警告 1 件。tokio の RUSTSEC-2026-0386 は既存のもので、許容済み)
aws-sdk-go-v2 AssumeRole(インライン Policy 付き)で得た一時認証情報を使い、GetParameter(WithDecryption) で SecureString を取得できた。存在しないパラメータは *types.ParameterNotFound として判定できた
aws-lambda-go 1.55.1(lambda.StartWithOptions、darwin 向けにビルド) 通常の呼び出し、2 回目の呼び出しでの実行環境の再利用、関数エラー(X-Amz-Function-Error: Unhandled)を確認。Linux 向けのバイナリは Runtime.InvalidEntrypoint とビルドのヒントを返した
pushone-csa の data_load の SQL(sql.go の文をそのまま psql と pgx の PgConn().Exec で実行) CSV / TSV / JSON の GZIP あり・なし 6 通りすべて取り込めた。別の接続で 2 回実行しても、前の接続の一時テーブルは見えなかった

redshift_external と cloudrun の dropped_instance_bounds... は、途中の実行で時々失敗しました。redshift_external は main でも 8 回中 3 回失敗するため、この PR とは関係のない既存の不安定なテストです。最後の全体実行ではどちらも通っています。

制約と、このPRで扱わないこと

  • Redshift の SQL エンドポイントは TLS に対応していません。pushone-csa の runner は sslmode=verify-full で接続するため、そのままでは接続できません。ローカルでの接続方法は CSA 側で対応する前提です。
  • S3 の virtual-hosted 形式は CSA 側で path-style を使う前提にしたため、この PR では扱いません。
  • Lambda で RIE を含まないコンテナイメージを実行する機能、CloudWatch Logs、Redshift の PostgreSQL バックエンドでの UNLOAD は、今後の課題です。
  • STS が発行した一時認証情報は、strict モードのサービスでは受け付けられません(relaxed では使えます)。

SSM serves PutParameter, GetParameter (SecureString with WithDecryption),
DeleteParameter, and DescribeParameters over AWS JSON 1.1, persisted to
state.json. STS serves AssumeRole (inline session policy accepted, not
evaluated) and GetCallerIdentity over the AWS Query protocol.
Default ports 18031 (ssm) and 18032 (sts). The dashboard lists SSM
parameter metadata via DescribeParameters only, so values never reach it.
A provided* function's bootstrap runs as a local process against a
per-environment Lambda Runtime API (invocation/next, response, error,
init/error, chunked responses with error trailers). Environments are reused
like interpreter runtimes. A missing or foreign-OS bootstrap fails with
Runtime.InvalidEntrypoint. Extensions may register but get no events.
…-client sessions

Each pgwire client now gets its own PostgreSQL connection, so temp tables,
SETs, and transactions stay with that client and end on disconnect (they
used to share one connection across clients).

COPY ... FROM 's3://bucket/prefix' is loaded by devcloud on that session:
text/DELIMITER, CSV, JSON 'auto', GZIP, IGNOREHEADER, NULL AS, EMPTYASNULL,
BLANKSASNULL, with Redshift's empty-field NULL rules. Authorization options
are ignored; unsupported options are refused. redshift-e2e covers a staged
temp-table load in every format.
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-11-03T03:33:57.251686Z 4e7b21a PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4e7b21a05a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread services/redshift/src/copy_backend.rs Resolved
Comment thread services/ssm/src/sigv4.rs Resolved
Parse every object under the prefix before writing, then send all INSERTs
as one simple Query so PostgreSQL applies them as a single implicit
transaction (inside an explicit transaction a failure aborts it, as a
failed COPY does on Redshift). Accept FROM after any whitespace, and detect
COPY on bytes so a statement starting with multi-byte text cannot panic.
The ssm/sts blocks were inserted between cloudRun's enabled flag and its
project/region, which then configured sts instead of Cloud Run.
SDKs sign the body's SHA-256 for these services without sending
x-amz-content-sha256; treating its absence as UNSIGNED-PAYLOAD rejected
correctly signed requests in strict mode.
@simota
simota merged commit ea70cbb into main Nov 3, 2026
2 checks passed
@simota
simota deleted the feat/csa-local-aws branch November 3, 2026 22:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant